package com.czollmann.android.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.joda.time.DateTime;

import android.content.ContentResolver;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.MediaStore.Images;

import com.czollmann.android.CallObject;
import com.czollmann.android.Constants;
import com.czollmann.android.ImageObject;
import com.czollmann.android.ObjectWrapper;
import com.czollmann.android.SMSObject;
import com.czollmann.android.StaticMethods;
import com.facebook.android.Facebook;

public class DataUtils {
  public static final Uri URI_SMS = Uri.parse("content://sms");
  public static final Uri URI_CALLS = CallLog.Calls.CONTENT_URI;
  public static final Uri URI_PICTURES = Images.Media.EXTERNAL_CONTENT_URI;

  public static void initializeData(ContentResolver contentResolver,
            SharedPreferences settings) {
    LogUtils.infolog("initializeData called, getting all contents");
    DateObjectWrapperUtils.clear();
    // sms
    if (settings.getBoolean(Constants.SETTINGS_SHOWMESSAGES, true)) {
      List<ObjectWrapper> smsObjects = DataUtils.getMessages(contentResolver, settings);
      LogUtils.infolog("got " + smsObjects.size() + " sms");
      DateObjectWrapperUtils.addObjectWrappersToDateObjectWrappers(smsObjects);
    }
    // call
    if (settings.getBoolean(Constants.SETTINGS_SHOWCALLS, true)) {
      List<ObjectWrapper> callObjects = DataUtils.getCalls(contentResolver, settings);
      LogUtils.infolog("got " + callObjects.size() + " calls");
      DateObjectWrapperUtils.addObjectWrappersToDateObjectWrappers(callObjects);
    }
    // images
    if (settings.getBoolean(Constants.SETTINGS_SHOWPICTURES, true)) {
      List<ObjectWrapper> imageObjects = DataUtils.getImages(contentResolver, settings);
      LogUtils.infolog("got " + imageObjects.size() + " images");
      DateObjectWrapperUtils.addObjectWrappersToDateObjectWrappers(imageObjects);
    }
    // facebook
    if (settings.getBoolean(Constants.SETTINGS_USEFACEBOOK, false)) {
      // List<ObjectWrapper> facebookObjects = DataUtils
      // .getFacebook(contentResolver);
      // DateObjectWrapperUtils
      // .addObjectWrappersToDateObjectWrappers(facebookObjects);
    }
    LogUtils.infolog("got " + DateObjectWrapperUtils.getDateObjectWrappers().size()
              + " dateObjectsWrappers / days");
    Collections.sort(DateObjectWrapperUtils.getDateObjectWrappers());
  }

  private static List<ObjectWrapper> getFacebook(ContentResolver contentResolver) {
    List<ObjectWrapper> objectWrappers = new ArrayList<ObjectWrapper>();
    Facebook facebook = StaticMethods.getFacebook();
    if (facebook != null) {
      try {
        String testString = facebook.request("me/home");
        LogUtils.debuglog(testString);
      }
      catch (Exception e) {
        LogUtils.errorlog("exception: " + e.getMessage());
      }
    }
    return objectWrappers;
  }

  public static List<ObjectWrapper> getImages(ContentResolver contentResolver,
            SharedPreferences settings) {
    List<ObjectWrapper> objectWrappers = new ArrayList<ObjectWrapper>();
    Cursor cursor = null;
    try {
      String[] projection = {Images.ImageColumns._ID, Images.ImageColumns.DATA,
          Images.ImageColumns.DISPLAY_NAME, Images.ImageColumns.TITLE,
          Images.ImageColumns.DATE_MODIFIED, Images.ImageColumns.DATE_MODIFIED,
          Images.ImageColumns.DATE_TAKEN};
      String sortOrderString = "%s";
      String selection = "";
      if (settings.getBoolean(Constants.SETTINGS_LIMIT_ENTRYS, true)) {
        int entries = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                      Constants.SETTINGS_LIMIT_MAX_ENTRYS);
        sortOrderString += " limit " + entries;
      } else {
        int days = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                   Constants.SETTINGS_LIMIT_MAX_DAYS);
        selection = Images.ImageColumns.DATE_TAKEN + " >= "
                  + new DateTime().minusDays(days).getMillis();
      }
      String sortOrder = String.format(sortOrderString, Images.ImageColumns.DATE_TAKEN
                + " desc");
      cursor = contentResolver.query(URI_PICTURES, projection, selection, null, sortOrder);
      if (cursor == null) {
        LogUtils.infolog("cursor is null. uri: " + CallLog.Calls.CONTENT_URI);
        return objectWrappers;
      }
      for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
        Long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(Images.ImageColumns.DATE_TAKEN));
        String name = cursor.getString(cursor.getColumnIndexOrThrow(Images.ImageColumns.DISPLAY_NAME));
        String path = cursor.getString(cursor.getColumnIndexOrThrow(Images.ImageColumns.DATA));
        ImageObject imageObject = new ImageObject(name);
        imageObject.setPath(path);
        ObjectWrapper objectWrapper = new ObjectWrapper(dateTaken, imageObject);
        objectWrappers.add(objectWrapper);
      }
    }
    catch (Exception e) {
      LogUtils.errorlog(e);
    }
    finally {
      cursor.close();
    }
    return objectWrappers;
  }

  public static List<ObjectWrapper> getCalls(ContentResolver contentResolver,
            SharedPreferences settings) {
    List<ObjectWrapper> objectWrappers = new ArrayList<ObjectWrapper>();
    Cursor cursor = null;
    try {
      String[] projection = {CallLog.Calls.CACHED_NAME, CallLog.Calls.NUMBER,
          CallLog.Calls.DATE, CallLog.Calls.TYPE};
      String sortOrderString = "%s";
      String selection = "";
      if (settings.getBoolean(Constants.SETTINGS_LIMIT_ENTRYS, true)) {
        int entries = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                      Constants.SETTINGS_LIMIT_MAX_ENTRYS);
        sortOrderString += " limit " + entries;
      } else {
        int days = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                   Constants.SETTINGS_LIMIT_MAX_DAYS);
        selection = CallLog.Calls.DATE + " >= "
                  + new DateTime().minusDays(days).getMillis();
      }
      String sortOrder = String.format(sortOrderString, CallLog.Calls.DATE + " desc");
      cursor = contentResolver.query(URI_CALLS, projection, selection, null, sortOrder);
      if (cursor == null) {
        LogUtils.infolog("cursor is null. uri: " + CallLog.Calls.CONTENT_URI);
        return objectWrappers;
      }
      ObjectWrapper lastObjectWrapper = null;
      for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
        Long date = cursor.getLong(cursor.getColumnIndexOrThrow(CallLog.Calls.DATE));
        String name = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.CACHED_NAME));
        String number = cursor.getString(cursor.getColumnIndexOrThrow(CallLog.Calls.NUMBER));
        int type = cursor.getInt(cursor.getColumnIndexOrThrow(CallLog.Calls.TYPE));
        CallObject callObject = new CallObject(name, number, type);
        ObjectWrapper objectWrapper = new ObjectWrapper(date, callObject);
        if (lastObjectWrapper == null || !lastObjectWrapper.equals(objectWrapper)) {
          if (lastObjectWrapper != null
                    && settings.getBoolean(Constants.SETTINGS_GROUPCALLS, true)) {
            CallObject lastCallObject = lastObjectWrapper.getCallObject();
            if (lastCallObject.getType() != callObject.getType()
                      || !lastCallObject.getNumber().equals(callObject.getNumber())) {
              lastObjectWrapper = objectWrapper;
              objectWrappers.add(objectWrapper);
            } else {
              lastCallObject.setCount(lastCallObject.getCount() + 1);
            }
          } else {
            lastObjectWrapper = objectWrapper;
            objectWrappers.add(objectWrapper);
          }
        }
      }
    }
    catch (Exception e) {
      LogUtils.errorlog(e);
    }
    finally {
      cursor.close();
    }
    return objectWrappers;
  }

  public static List<ObjectWrapper> getMessages(ContentResolver contentResolver,
            SharedPreferences settings) {
    Uri mSmsQueryUri = URI_SMS;
    List<ObjectWrapper> objectWrappers = new ArrayList<ObjectWrapper>();
    Cursor cursor = null;
    try {
      String[] projection = {"date", "body", "type", "address", "person"};
      String sortOrderString = "%s";
      String selection = "";
      if (settings.getBoolean(Constants.SETTINGS_LIMIT_ENTRYS, true)) {
        int entries = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                      Constants.SETTINGS_LIMIT_MAX_ENTRYS);
        sortOrderString += " limit " + entries;
      } else {
        int days = settings.getInt(Constants.SETTINGS_LIMIT_COUNT,
                                   Constants.SETTINGS_LIMIT_MAX_DAYS);
        selection = "date" + " >= " + new DateTime().minusDays(days).getMillis();
      }
      String sortOrder = String.format(sortOrderString, "date desc");
      cursor = contentResolver.query(mSmsQueryUri, projection, selection, null, sortOrder);
      if (cursor == null) {
        LogUtils.infolog("cursor is null. uri: " + mSmsQueryUri);
        return objectWrappers;
      }
      ObjectWrapper lastObjectWrapper = null;
      for (boolean hasData = cursor.moveToFirst(); hasData; hasData = cursor.moveToNext()) {
        Long date = cursor.getLong(cursor.getColumnIndexOrThrow("date"));
        String body = cursor.getString(cursor.getColumnIndexOrThrow("body"));
        SMSObject smsObject = new SMSObject(body);
        smsObject.setType(cursor.getInt(cursor.getColumnIndexOrThrow("type")));
        smsObject.setNumber(cursor.getString(cursor.getColumnIndexOrThrow("address")));
        smsObject.setPerson(cursor.getString(cursor.getColumnIndexOrThrow("person")));
        ObjectWrapper objectWrapper = new ObjectWrapper(date, smsObject);
        if (lastObjectWrapper == null || !lastObjectWrapper.equals(objectWrapper)) {
          lastObjectWrapper = objectWrapper;
          objectWrappers.add(objectWrapper);
        }
      }
    }
    catch (Exception e) {
      LogUtils.errorlog(e);
    }
    finally {
      cursor.close();
    }
    return objectWrappers;
  }
}
